package com.iocup.keybastion.sso.core;


import com.iocup.keybastion.core.lock.LocalLock;
import com.iocup.keybastion.core.lock.Lock;
import com.iocup.keybastion.core.lock.LockType;
import com.iocup.keybastion.core.store.CacheStore;
import com.iocup.keybastion.sso.TicketService;
import com.iocup.keybastion.sso.common.TicketRequestParam;
import com.iocup.keybastion.sso.config.SsoProperties;
import com.pine.sunflower.core.validate.Validator;

/**
 * @author xyjxust
 * @create 2022/3/18 16:53
 **/
public class DefaultTicketService implements TicketService {

    private SsoProperties ssoProperties;
    private CacheStore cacheStore;
    private Lock lock;

    private static final String TICKET_SESSION_KEY = "TICKET:SESSION:";

    private static final String SESSION_ID_TICKET_KEY = "SESSION:ID:TICKET:";

    public DefaultTicketService(Lock lock, SsoProperties ssoProperties, CacheStore cacheStore) {
        Validator.build().validate(cacheStore == null, "tokenStore不能为空")
                .validate(ssoProperties == null, "ssoProperties不能为空")
                .throwIfFail();
        this.lock = lock;
        if (lock == null) {
            this.lock = new LocalLock();
        }
        this.cacheStore = cacheStore;
        this.ssoProperties = ssoProperties;
    }

    @Override
    public TicketRequestParam getByTicket(String ticket) {
        return this.cacheStore.getValue(buildTicketSessionKey(ticket));
    }

    @Override
    public void saveTicket(String ticket, TicketRequestParam ticketRequestParam) {
        this.lock.tryLock(LockType.SESSION_ID, ticketRequestParam.getSessionId(), key -> {
            this.cacheStore.setValue(buildTicketSessionKey(ticket), ticketRequestParam, this.ssoProperties.getTicketValiditySeconds());
            this.cacheStore.setValue(buildSessionTicketKey(ticketRequestParam.getSessionId()), ticket, this.ssoProperties.getTicketValiditySeconds());
        });

    }

    @Override
    public void removeTicket(String ticket) {
       TicketRequestParam ticketRequestParam =  this.cacheStore.getValue(buildTicketSessionKey(ticket));
       if(ticketRequestParam!=null){
           this.lock.tryLock(LockType.SESSION_ID, ticketRequestParam.getSessionId(), key -> {
               this.cacheStore.removeValue(buildTicketSessionKey(ticket));
               this.cacheStore.removeValue(buildSessionTicketKey(ticketRequestParam.getSessionId()));
           });
       }

    }

    @Override
    public String getTicketBySessionId(String sessionId) {
        return this.cacheStore.getValue(buildSessionTicketKey(sessionId));
    }

    private String buildTicketSessionKey(String ticket) {
        return String.format("%s%s:", TICKET_SESSION_KEY, ticket);
    }

    private String buildSessionTicketKey(String ticket) {
        return String.format("%s%s:", SESSION_ID_TICKET_KEY, ticket);
    }
}
